import axios from 'axios';
import store from '../store';
import { Toast } from 'vant'

class HttpRequest {
  queue = {} // 请求的url集合
  destroy(url) {
    delete this.queue[url]
    if (!Object.keys(this.queue).length) {
      /*hide loading*/
    }
  }
  interceptors(instance, url) {
    // 请求拦截
    instance.interceptors.request.use((config) => {
      // 添加全局的loading...
      if (!Object.keys(this.queue).length) {
        /*show loading*/
      }
      if (url) {
        this.queue[url] = true;
      }
      return config;
    }, (error) => {
      console.error(error);
    })
    // 响应拦截
    instance.interceptors.response.use((res) => {
      if (url) {
        this.destroy(url);
      }
      const { data, status } = res;
      if (status === 200 && data && data.success) {
        return data.dataList;
      } else {
        return requestFail(status, data.reason); // 失败回调
      }
    }, (error) => {
      console.log(error);
      console.log(error.response);
      if (url) {
        this.destroy(url);
      } 
      let status = error.response.status;
      return requestFail(error.response ? error.response.status : 200, error.response ? error.response.reason : '');
    })
  }
  // 注册异步方法
  async request(options) {
    const instance = axios.create()
    await this.interceptors(instance, options.url)
    return instance(options)
  }
}

// 请求失败
const requestFail = (code, reason) => {
  if (code === 401 || code == 403) return store.commit('exit');
  store.commit('loading');
  Toast(reason);
  return Promise.reject({
    code,
    reason
  });
}

// 合并axios参数
const conbineOptions = (method, url, data) => {
  let headers = store.state.userInfo.token ? { 'X-Access-Token': store.state.userInfo.token } : {};
  let options = { method, url, headers, params: null, data: null };
  if (data) {
    if (data && data.query && data.query instanceof Object) {
      options.params = { ...data.query, _: new Date().getTime() };
    };
    if (data && data.body && data.body instanceof Object) {
      options.data = data.body;
    };
    if (options.params || options.data) {

    } else if (method == 'GET' || method == 'DELETE') {
      options.params = { ...data, _: new Date().getTime() };
    } else {
      options.data = data;
    }
  }
  return options
}
const HTTP = new HttpRequest()

const Api = (() => {
  const apiObj = {};
  const requestMethods = {
    get: 'GET',
    delete: 'DELETE',
    post: 'POST',
    put: 'PUT'
  };
  const fun = (method) => {
    return async (url, data) => {
      const newOpts = conbineOptions(method, url, data)
      const res = await HTTP.request(newOpts)
      return res
    }
  }
  Object.keys(requestMethods).forEach((method) => {
    apiObj[method] = fun(requestMethods[method]);
  });
  return apiObj;
})()

export default Api;
